package com.gxp.web.controller;

import com.gxp.common.config.GxPConfig;
import com.gxp.common.constant.AutomationConstants;
import com.gxp.common.core.controller.BaseController;
import com.gxp.common.core.domain.AjaxResult;
import com.gxp.common.core.domain.entity.SysUser;
import com.gxp.common.utils.DateUtils;
import com.gxp.common.utils.DictUtils;
import com.gxp.common.utils.StringUtils;
import com.gxp.common.utils.file.FileUploadUtils;
import com.gxp.system.domain.*;
import com.gxp.system.domain.dto.GxpUserDto;
import com.gxp.system.domain.dto.ZkDoneExpInfoDto;
import com.gxp.system.service.*;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 处理SSJ的请求
 */
@Controller
@RequestMapping("/upload")
public class SSJExPController extends BaseController {

    @Autowired
    private IZkAutoExpinfoService autoExpinfoService;
    @Autowired
    private IZkPendingExpService pendingExpService;
    @Autowired
    private IZkNmrFileService nmrFileService;
    @Autowired
    private IZknjServiceInstanceService aServiceService;
    @Autowired
    private IZknjRequestService requestService;
    @Autowired
    private ISSJService ssjService;
    @Autowired
    private IZknjServiceApproveService serviceApproveService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IZkInstrumentService instrumentService;

    //拉取实验成功标志
    private final int ADD_AUTO_EXP_SUCCESS = 1;
    //拉取实验失败标志
    private final int ADD_AUTO_EXP_ERROR = 2;

    /**
     * SSJ定时上传自动化实验数据(user==gxp)
     * @param expinfoString
     * @return
     */
    @PostMapping("/expinfo.do")
    @ResponseBody
    public AjaxResult expInfoSy(String expinfoString){
        if(StringUtils.isEmpty(expinfoString)){
            AjaxResult error = AjaxResult.error();
            error.put("code", 400);
            error.put("data","expinfoString is empty");
            logger.error("expinfoString is empty");
            return error;
        }
        logger.info("expInfoSy expinfoString = {}", expinfoString);
        //保存数据
        autoExpinfoService.updateExpinfo(expinfoString);
        //更新Service进程
        aServiceService.updateProcess();
        return success().put("code", 200);
    }

    /**
     * SSJ拉取待提交实验数据
     * @param hostId 仪器HostId
     */
    @PostMapping("/pendingexps.do")
    @ResponseBody
    public AjaxResult getPendingExp(@Param("hostId") String hostId){
        if(StringUtils.isEmpty(hostId)){
            AjaxResult error = AjaxResult.error();
            error.put("code", 400);
            error.put("data","hostId is empty");
            logger.error("hostId is empty");
            return error;
        }
        logger.info("getPendingExp hostId = {}", hostId);
        //根据hostId查询仪器信息
        ZkInstrument instrument = instrumentService.selectZkInstrumentByHostId(hostId);
        if(instrument == null){
            AjaxResult error = AjaxResult.error();
            error.put("code", 401);
            error.put("data","instrument == null");
            logger.error("instrument == null");
            return error;
        }
        ZkPendingExp pendingExp = new ZkPendingExp();
        pendingExp.setHostId(hostId);
        //查询数据库数据
        List<ZkPendingExp> pendingExps = pendingExpService.selectZkPendingExpList(pendingExp);
        //修改 Request 状态为 pending result
        if(!StringUtils.isEmpty(pendingExps)){
            requestService.updateStatus(pendingExps.stream().map(ZkPendingExp::getExpcode).collect(Collectors.toList()),
                    Long.valueOf(DictUtils.getDictValue("sys_request_status","pending results")));
        }else {
            //如果没有数据,返回201状态码
            AjaxResult success = AjaxResult.success();
            success.put("code",201);
            success.put("data", "No pending experiments found");
            return success;
        }
        return success().put("code",200).put("data",pendingExps);
    }

    /**
     * SSJ第一次返回拉取结果
     * @param expcodes 拉取的实验expcode
     * @return
     */
    @PostMapping("/pendingexpRes.do")
    @ResponseBody
    public AjaxResult pendingexpRes(@RequestParam("expcodes")String expcodes){
        pendingExpService.pendingexpRes(expcodes);
        AjaxResult success = AjaxResult.success();
        success.put("code",200);
        return success;
    }

    /**
     * SSJ第二次返回处理结果（成功或者失败）
     * @param expcode
     * @param result
     * @return
     */
    @PostMapping("/addAutoExpRes.do")
    @ResponseBody
    public AjaxResult addAutoExpRes(@Param("expcode")String expcode, @Param("result")Integer result, @Param("msg")String msg){
        //在pendingexp表中查询type
        ZkPendingExp pendingExp = pendingExpService.selectZkPendingExpByExpcode(expcode);
        if(pendingExp == null){
            AjaxResult error = AjaxResult.error();
            error.put("code", 400);
            error.put("data","pendingExp == null");
            logger.error("pendingExp == null");
            return error;
        }
        //根据实验类型处理结果 TODO：暂时只支持提交实验，后续优化
        if(pendingExp.getType() == AutomationConstants.EXP_TYPE_SUBMIT){
            ZknjServiceInstance active = aServiceService.selectZkServiceInstanceByExpcode(expcode);
            ZknjServiceInstance serviceActive = new ZknjServiceInstance();
            serviceActive.setInfId(active.getInfId());
            serviceActive.setResMsg(msg);
            if(result == ADD_AUTO_EXP_ERROR){
                //添加自动化实验失败
                serviceActive.setProcess(Long.valueOf(DictUtils.getDictValue("auto_exp_status","Error")));
            }else if (result == ADD_AUTO_EXP_SUCCESS){
                //添加自动化实验成功
                serviceActive.setProcess(Long.valueOf(DictUtils.getDictValue("auto_exp_status","Queued")));
            }
            //修改Service状态
            aServiceService.updateZknjServiceInstance(serviceActive);
            //修改request状态
            if(result == ADD_AUTO_EXP_ERROR){
                requestService.updateStatus(expcode, Long.valueOf(DictUtils.getDictValue("sys_request_status","error")));
            }

        }else if(pendingExp.getType() == AutomationConstants.EXP_TYPE_STOP){
            //停止不做任何处理

        }
        //pending_exp表处理
        pendingExpService.submitAutoExpRes(expcode,result);
        return success().put("code",200);
    }

    /**
     * SSJ上传实验完成结果nmr文件和上传处理文件
     * @param expcode
     * @param type 1:原始nmr文件 2:处理nmr文件
     * @param nmrfile nmr文件
     * @param filename 文件名
     * @param reportfile pdf报告
     * @return
     */
    @PostMapping("/nmrfile.do")
    @ResponseBody
    public AjaxResult sendNMRFile(String expcode, String type, String filename, MultipartFile nmrfile, MultipartFile reportfile){
        logger.info("sendNMRFile expcode = {}, type = {}, filename = {}, nmrfile = {}, reportfile = {}", expcode, type, filename, nmrfile != null ? nmrfile.getOriginalFilename() : "null", reportfile != null ? reportfile.getOriginalFilename() : "null");
        try {
            //根据expcode获取服务
            ZknjServiceInstance service = aServiceService.selectZkServiceInstanceByExpcode(expcode);
            if(service == null){
                AjaxResult error = AjaxResult.error();
                error.put("code", 400);
                error.put("data","service == null");
                logger.error("service == null");
                return error;
            }
            //保存文件
            String filepath = FileUploadUtils.upload2(GxPConfig.getUploadPath(),nmrfile);
            //保存文件路径到数据库
            ZkNmrFile nmrFile = new ZkNmrFile();
            nmrFile.setUploadTime(DateUtils.getNowDate());
            if(filename == null || filename.isEmpty()){
                filename = nmrfile.getOriginalFilename();
            }
            nmrFile.setFileName(filename);
            nmrFile.setFilePathGxp(filepath);
            nmrFile.setFileSize(nmrfile.getSize());
            nmrFileService.insertZkNmrFile(nmrFile);

            //如果有处理文件，保存处理文件
            if(reportfile != null && !reportfile.isEmpty()){
                String destFilePath = FileUploadUtils.upload2(GxPConfig.getUploadPath(),reportfile);
                ZkNmrFile destNmrFile = new ZkNmrFile();
                destNmrFile.setUploadTime(DateUtils.getNowDate());
                destNmrFile.setFileName(reportfile.getOriginalFilename());
                destNmrFile.setFilePathGxp(destFilePath);
                destNmrFile.setFileSize(reportfile.getSize());
                nmrFileService.insertZkNmrFile(destNmrFile);
                //更新Service的处理文件
                ZknjServiceInstance service2 = new ZknjServiceInstance();
                service2.setInfId(service.getInfId());
                service2.setReportfileIds(destNmrFile.getFileId()+"");
                aServiceService.updateZknjServiceInstance(service2);
            }
            if(type.equals("1")){
                //修改Service状态
                ZknjServiceInstance service2 = new ZknjServiceInstance();
                service2.setInfId(service.getInfId());
                service2.setNmrfileId(nmrFile.getFileId());
                service2.setSerStatus(Long.valueOf(DictUtils.getDictValue("sys_service_status","pending verification")));
                aServiceService.updateZknjServiceInstance(service2);
                //查询是否都完成，都完成修改Request状态
                aServiceService.checkServiceInstanceStatus(service.getInfId());

            }else if (type.equals("2")){
//                String anaNmrfileIds = aServiceService.selectByInfId(service.getInfId()).getAnaNmrfileIds();
                String anaNmrfileIds = service.getAnaNmrfileIds();
                if(StringUtils.isEmpty(anaNmrfileIds)) {
                    anaNmrfileIds = nmrFile.getFileId().toString();
                }else {
                    anaNmrfileIds = anaNmrfileIds + "," + nmrFile.getFileId();
                }
                ZknjServiceInstance service2 = new ZknjServiceInstance();
                service2.setInfId(service.getInfId());
                service2.setAnaNmrfileIds(anaNmrfileIds);
                aServiceService.updateZknjServiceInstance(service2);
            }
        } catch (IOException e) {
            return error("System Error: " + e.getMessage()).put("code",400);
        }
        AjaxResult success = AjaxResult.success();
        success.put("code",200);
        return success;
    }

    /**
     * 连接测试
     */
    @PostMapping("/test.do")
    @ResponseBody
    public AjaxResult test(){
        System.out.println("test1");
        AjaxResult success = AjaxResult.success();
        success.put("code",200);
        return success;
    }

    // 测试，便于获取非加密文件
    @PostMapping("/uploadtest.do")
    @ResponseBody
    public AjaxResult uploadTest(MultipartFile file){
        System.out.println("file.getOriginalFilename() = " + file.getOriginalFilename());
        try {
            //保存文件
            file.transferTo(new File("C:\\Users\\ZH\\Desktop\\taishiji\\" + file.getOriginalFilename()));
        } catch (IOException e) {
            return error(e.getMessage()).put("code",400);
        }
        return success().put("code",200);
    }

    /**
     * ssj拉取已完成实验的信息(只返回目录结构，下载时再获取具体信息)
     */
    @PostMapping("/doneExpinfos.do")
    @ResponseBody
    public AjaxResult getDoneExpInfos(@Param("username")String username, @Param("rolename")String rolename, @Param("startTime")String startTime, @Param("endTime")String endTime){
        logger.info("getDoneExpInfos username = {}, rolename = {}, startTime = {}, endTime = {}", username, rolename, startTime, endTime);
        List<ZkDoneExpInfoDto> data  = ssjService.getDoneExpInfos(username, rolename, startTime, endTime);
        return success().put("code",200).put("data",data);
    }

    /**
     * ssj拉取已完成实验的信息
     */
    @PostMapping("/doneExpinfosbyexpcodes.do")
    @ResponseBody
    public AjaxResult getDoneExpInfos(@Param("expcodes")List<String> expcodes){
        logger.info("getDoneExpInfos expcodes = {}", expcodes);
        List<ZkDoneExpInfoDto> data  = ssjService.getDoneExpInfos(expcodes);
        return success().put("code",200).put("data",data);
    }

    /**
     * 根据expcode获取已经存在的nmr文件名称，包括处理文件,用于重名检测
     */
    @PostMapping("/getExistFileNames.do")
    @ResponseBody
    public AjaxResult getExistFileNames(@Param("expcode")String expcode){
        logger.info("getExistFileNames expcode = {}", expcode);
        ZknjServiceInstance service = aServiceService.selectZkServiceInstanceByExpcode(expcode);
        if(service == null){
            AjaxResult error = AjaxResult.error();
            error.put("code", 400);
            error.put("data","service == null");
            logger.error("service == null");
            return error;
        }
        List<String> fileNames = nmrFileService.selectNmrFileByInfId(service.getInfId()).stream().map(ZkNmrFile::getFileName).collect(Collectors.toList());
        return success().put("code",200).put("data",fileNames);
    }

    /**
     * 获取审批人
     * @param expcode
     * @return
     */
    @PostMapping("/approvers.do")
    @ResponseBody
    public AjaxResult getApprovers(@Param("expcode")String expcode){
        logger.info("getApprovers expcode = {}", expcode);
        List<GxpUserDto> approvers = ssjService.getApprovers(expcode);
        return success().put("code",200).put("data",approvers);
    }

    /**
     * 提交专家审核
     */
    @PostMapping("/submit.do")
    @ResponseBody
    public AjaxResult submit(String expcode, Long approveBy, MultipartFile nmrfile){
        logger.info("submit expcode = {}, approveBy = {}, nmrfile = {}", expcode, approveBy, nmrfile != null ? nmrfile.getOriginalFilename() : "null");
        ZknjServiceInstance instance = aServiceService.selectZkServiceInstanceByExpcode(expcode);
        SysUser approveUser = userService.selectUserById(approveBy);
        if(approveUser == null){
            AjaxResult error = AjaxResult.error();
            error.put("code", 400);
            error.put("data","approveUser == null");
            logger.error("approveUser == null");
            return error;
        }
        if(instance == null){
            AjaxResult error = AjaxResult.error();
            error.put("code", 400);
            error.put("data","service == null");
            logger.error("service == null");
            return error;
        }
        try {
            //保存文件
            String filepath = FileUploadUtils.upload2(GxPConfig.getUploadPath(),nmrfile);
            //保存文件路径到数据库
            ZkNmrFile nmrFile = new ZkNmrFile();
            nmrFile.setUploadTime(DateUtils.getNowDate());
            nmrFile.setFileName(nmrfile.getOriginalFilename());
            nmrFile.setFilePathGxp(filepath);
            nmrFile.setFileSize(nmrfile.getSize());
            nmrFileService.insertZkNmrFile(nmrFile);
            //修改Service状态
            ZknjServiceApprove serviceApprove = new ZknjServiceApprove();
            serviceApprove.setApproveBy(approveUser.getLoginName());
            serviceApprove.setApproveFileId(nmrFile.getFileId());
            serviceApprove.setExpcode(expcode);
            serviceApprove.setCreateTime(DateUtils.getNowDate());
            serviceApprove.setApproveStatus(0l);    //待审核
            serviceApproveService.insertZknjServiceApprove(serviceApprove);

            ZknjServiceInstance serviceInstance = new ZknjServiceInstance();
            serviceInstance.setInfId(instance.getInfId());
            serviceInstance.setSerStatus(Long.valueOf(DictUtils.getDictValue("sys_service_status","pending verification")));
            String anaNmrfileIds = instance.getAnaNmrfileIds();
            if(StringUtils.isEmpty(anaNmrfileIds)) {
                anaNmrfileIds = nmrFile.getFileId().toString();
            }else {
                anaNmrfileIds = anaNmrfileIds + "," + nmrFile.getFileId();
            }
            serviceInstance.setAnaNmrfileIds(anaNmrfileIds);
            aServiceService.updateZknjServiceInstance(serviceInstance);
        }catch (IOException e){
            e.printStackTrace();
            return error(e.getMessage()).put("code",400).put("data", "System Error");
        }
        AjaxResult success = AjaxResult.success();
        success.put("code",200);
        return success;
    }

    /**
     * 审核结果
     */
    @PostMapping("/approveResult.do")
    @ResponseBody
    public AjaxResult approveResult(@Param("expcode")String expcode, @Param("comment")String comment, MultipartFile nmrfile){
//        ZknjServiceApprove serviceApprove = serviceApproveService.selectZknjServiceApproveByExpcode(expcode);
//        if(serviceApprove == null){
//            AjaxResult error = AjaxResult.error();
//            error.put("code", 400);
//            error.put("data","serviceApprove == null");
//            logger.error("serviceApprove == null");
//            return error;
//        }
//
//        serviceApprove.setApproveStatus(1l); //已审核
//        serviceApprove.setApproveComment(comment);
//
//        //修改文件路径
//        if(nmrfile != null && !nmrfile.isEmpty()){
//            try {
//                //保存文件
//                String filepath = FileUploadUtils.upload2(GxPConfig.getUploadPath(),nmrfile);
//                //保存文件路径到数据库
//                ZkNmrFile nmrFile = new ZkNmrFile();
//                nmrFile.setUploadTime(DateUtils.getNowDate());
//                nmrFile.setFileName(nmrfile.getOriginalFilename());
//                nmrFile.setFilePathGxp(filepath);
//                nmrFile.setFileSize(nmrfile.getSize());
//                nmrFileService.insertZkNmrFile(nmrFile);
//                Long oldApproveFileId = serviceApprove.getApproveFileId();
//                String oldFilepath = GxPConfig.getProfile() + "/" + serviceApprove.getApproveFile().getFilePathGxp();
//                serviceApprove.setApproveFileId(nmrFile.getFileId());
//                //删除之前的文件
//                if(!oldFilepath.isEmpty()){
//                    File oldFile = new File(oldFilepath);
//                    if(oldFile.exists()){
//                        oldFile.delete();
//                        nmrFileService.deleteZkNmrFileByFileId(oldApproveFileId);
//                    }
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//                return error(e.getMessage()).put("code",400).put("data", "System Error");
//            }
//        }
//
//        serviceApproveService.updateZknjServiceApprove(serviceApprove);
//        //修改Service状态
//        ZknjServiceInstance serviceInstance = new ZknjServiceInstance();
//        serviceInstance.setInfId(aServiceService.selectZkServiceInstanceByExpcode(expcode).getInfId());
//        serviceInstance.setSerStatus(Long.valueOf(DictUtils.getDictValue("sys_service_status","verified")));
//        aServiceService.updateZknjServiceInstance(serviceInstance);
        AjaxResult success = AjaxResult.success();
        success.put("code",200);
        return success;
    }
}
